package com.live.stamp.base.service.impl;

import com.hikeSoft.common.utils.BaseUtils;
import com.hikeSoft.common.utils.SqlUtils;
import com.hikeSoft.common.utils.UUIDUtils;
import com.live.stamp.base.service.ISqlDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.container.core.common.*;
import org.springframework.boot.container.core.dao.BaseSupportDaoImpl;
import org.springframework.boot.container.core.dao.DTOPropertyRowMapper;
import org.springframework.boot.container.core.dao.ModelPropertyRowMapper;
import org.springframework.boot.container.core.dao.dialect.*;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @author cwd E-mail: wendong.cao@jsxfedu.com
 * @version 1
 * @date 2018/4/13 11:00
 */
public class SqlBaseSupportDaoImpl extends NamedParameterJdbcDaoSupport implements ISqlDao {
    private static final Logger logger = LoggerFactory.getLogger(BaseSupportDaoImpl.class);
    private static final String SQL_TYPES = "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR";
    private static final String[] sqlRegexps = new String[]{"(?i)(.*)(\\b)+SELECT(\\b)+\\s.*(\\b)+FROM(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+INSERT(\\b)+\\s.*(\\b)+INTO(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+UPDATE(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+DELETE(\\b)+\\s.*(\\b)+FROM(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+UPSERT(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+SAVEPOINT(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+CALL(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+ROLLBACK(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+KILL(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+DROP(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+CREATE(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+ALTER(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+TRUNCATE(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+LOCK(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+UNLOCK(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+RELEASE(\\b)+(\\s)*(" + "TABLE, TABLESPACE, PROCEDURE, FUNCTION, TRIGGER, KEY, VIEW, MATERIALIZED VIEW, LIBRARYDATABASE LINK, DBLINK, INDEX, CONSTRAINT, TRIGGER, USER, SCHEMA, DATABASE, PLUGGABLE DATABASE, BUCKET, CLUSTER, COMMENT, SYNONYM, TYPE, JAVA, SESSION, ROLE, PACKAGE, PACKAGE BODY, OPERATORSEQUENCE, RESTORE POINT, PFILE, CLASS, CURSOR, OBJECT, RULE, USER, DATASET, DATASTORE, COLUMN, FIELD, OPERATOR".replaceAll(",", "|") + ")(\\b)+\\s.*(.*)", "(?i)(.*)(\\b)+DESC(\\b)+(\\w)*\\s.*(.*)", "(?i)(.*)(\\b)+DESCRIBE(\\b)+(\\w)*\\s.*(.*)", "(.*)(/\\*|\\*/|;){1,}(.*)", "(.*)(-){2,}(.*)"};
    private List<Pattern> validationPatterns = getValidationPatterns();
    private String dialect;

    public SqlBaseSupportDaoImpl(DataSource dataSource, String dialect) {
        this.dialect = dialect;
        super.setDataSource(dataSource);
    }

    public int exec(String sql) throws SQLException {
        return this.exec(sql, (Object[])null);
    }

    public int exec(String sql, final Object[] param) throws SQLException {
        logger.debug("SQL:" + sql);
        return ((Integer)this.getJdbcTemplate().execute(sql, new PreparedStatementCallback<Integer>() {
            public Integer doInPreparedStatement(PreparedStatement tmt) throws SQLException {
                if (param != null && param.length > 0) {
                    int i = 0;

                    for(int len = param.length; i < len; ++i) {
                        if (param[i] != null && param[i].getClass().isEnum()) {
                            tmt.setString(i + 1, param[i].toString());
                        } else {
                            tmt.setObject(i + 1, param[i]);
                        }
                    }
                }

                return tmt.executeUpdate();
            }
        })).intValue();
    }

    public int exec(String sql, Map<String, Object> param) throws SQLException {
        logger.debug("SQL:" + sql);
        return ((Integer)this.getNamedParameterJdbcTemplate().execute(sql, param, new PreparedStatementCallback<Integer>() {
            public Integer doInPreparedStatement(PreparedStatement tmt) throws SQLException, DataAccessException {
                return tmt.executeUpdate();
            }
        })).intValue();
    }

    public int exec(String sql, Object param) throws SQLException {
        logger.debug("SQL:" + sql);
        SqlParameterSource ps = new BeanPropertySqlParameterSource(param);
        return ((Integer)this.getNamedParameterJdbcTemplate().execute(sql, ps, new PreparedStatementCallback<Integer>() {
            public Integer doInPreparedStatement(PreparedStatement tmt) throws SQLException, DataAccessException {
                return tmt.executeUpdate();
            }
        })).intValue();
    }

    public int[] execBatch(List<String> sqls) throws SQLException {
        return sqls != null ? this.getJdbcTemplate().batchUpdate((String[])sqls.toArray(new String[sqls.size()])) : null;
    }

    public int[] execBatch(String sql, List<Object[]> params) throws SQLException {
        logger.debug("SQL:" + sql);
        return this.getJdbcTemplate().batchUpdate(sql, params);
    }

    public int[] execBatch(String sql, Map<String, Object>[] params) throws SQLException {
        logger.debug("SQL:" + sql);
        return this.getNamedParameterJdbcTemplate().batchUpdate(sql, params);
    }

    public int[] execBatch(String sql, Object[] params) throws SQLException {
        logger.debug("SQL:" + sql);
        List<SqlParameterSource> psList = new ArrayList();
        if (params != null) {
            psList = (List) Arrays.asList(params).parallelStream().map((o) -> {
                return new BeanPropertySqlParameterSource(o);
            }).collect(Collectors.toList());
        }

        return this.getNamedParameterJdbcTemplate().batchUpdate(sql, (SqlParameterSource[])((List)psList).toArray(new SqlParameterSource[((List)psList).size()]));
    }

    public int insert(String table, final Map<String, Object> bean) throws SQLException {
        if (bean == null) {
            logger.error("bean is null");
            throw new SQLException("bean is null");
        } else {
            final List<String> column = new ArrayList();
            String sql = "INSERT INTO " + table + "($field$) VALUES($value$)";
            String fields = "";
            String values = "";
            Iterator it = bean.keySet().iterator();

            while(it.hasNext()) {
                String key = (String)it.next();
                if (bean.get(key) != null) {
                    fields = fields + "," + key;
                    values = values + ",?";
                    column.add(key);
                }
            }

            if ("".equals(fields)) {
                logger.error("bean is empty");
                throw new SQLException("bean is empty");
            } else {
                sql = sql.replace("$field$", fields.substring(1, fields.length()));
                sql = sql.replace("$value$", values.substring(1, values.length()));
                logger.debug("SQL:" + sql);
                return ((Integer)this.getJdbcTemplate().execute(sql, new PreparedStatementCallback<Integer>() {
                    public Integer doInPreparedStatement(PreparedStatement tmt) throws SQLException {
                        int j = 0;

                        for(int len = column.size(); j < len; ++j) {
                            Object obj = bean.get(column.get(j));
                            if (obj != null && obj.getClass().isEnum()) {
                                tmt.setString(j + 1, obj.toString());
                            } else {
                                tmt.setObject(j + 1, obj);
                            }
                        }

                        return tmt.executeUpdate();
                    }
                })).intValue();
            }
        }
    }

    public int insert(Object model) throws SQLException {
        if (model != null && model instanceof BaseModel) {
            ServerModel serverModel = (ServerModel)model.getClass().getAnnotation(ServerModel.class);
            Map<String, Object> bean = (Map)Arrays.asList(model.getClass().getDeclaredFields()).parallelStream().filter((o) -> {
                return !o.getName().equalsIgnoreCase("serialVersionUID") && !o.isSynthetic() && o.getAnnotation(ServerIgnore.class) == null;
            }).collect(toMap((o) -> {
                ServerField serverField = (ServerField)o.getAnnotation(ServerField.class);
                return serverField != null ? serverField.value() : o.getName();
            }, (o) -> {
                o.setAccessible(true);

                try {
                    return o.get(model);
                } catch (Exception var3) {
                    logger.error("insert error:" + var3.getMessage());
                    return null;
                }
            }));
            bean.put("ID", ((BaseModel)model).getId());
            return this.insert(serverModel != null ? serverModel.value() : model.getClass().getSimpleName(), bean);
        } else {
            throw new SQLException("业务对象为空或不正确");
        }
    }

    public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) {
        return Collectors.collectingAndThen(Collectors.toList(), (list) -> {
            Map<K, U> result = new HashMap();
            Iterator var4 = list.iterator();

            while(var4.hasNext()) {
                T item = (T) var4.next();
                result.putIfAbsent(keyMapper.apply(item), valueMapper.apply(item));
            }

            return result;
        });
    }

    public int[] insertBatch(String table, final List<Map<String, Object>> records) throws SQLException {
        if (records != null && records.size() > 0) {
            Map<String, Object> bean = (Map)records.get(0);
            if (bean == null) {
                logger.error("bean is null");
                throw new SQLException("bean is null");
            } else {
                final String[] column = new String[bean.size()];
                String sql = "INSERT INTO " + table + "($field$) VALUES($value$)";
                String fields = "";
                String values = "";
                Iterator<String> it = bean.keySet().iterator();

                for(int i = 0; it.hasNext(); ++i) {
                    String key = (String)it.next();
                    column[i] = key;
                    if ("".equalsIgnoreCase(fields)) {
                        fields = key;
                        values = "?";
                    } else {
                        fields = fields + "," + key;
                        values = values + ",?";
                    }
                }

                if ("".equals(fields)) {
                    logger.error("bean is empty");
                    throw new SQLException("bean is empty");
                } else {
                    sql = sql.replace("$field$", fields);
                    sql = sql.replace("$value$", values);
                    logger.debug("SQL:" + sql);
                    return this.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
                        public void setValues(PreparedStatement tmt, int i) throws SQLException {
                            Map<String, Object> o = (Map)records.get(i);
                            int j = 0;

                            for(int len = column.length; j < len; ++j) {
                                Object obj = o.get(column[j]);
                                if (obj != null && obj.getClass().isEnum()) {
                                    tmt.setString(j + 1, obj.toString());
                                } else {
                                    tmt.setObject(j + 1, obj);
                                }
                            }

                        }

                        public int getBatchSize() {
                            return records.size();
                        }
                    });
                }
            }
        } else {
            return null;
        }
    }

    public int[] insertBatch(List<? extends Object> models) throws SQLException {
        try {
            if (models != null && models.size() > 0) {
                Object model = models.get(0);
                ServerModel serverModel = (ServerModel)model.getClass().getAnnotation(ServerModel.class);
                String sql = "INSERT INTO " + (serverModel != null ? serverModel.value() : model.getClass().getSimpleName()) + "($field$) VALUES($value$)";
                String fields = "ID";
                String values = ":ID";
                Field[] var7 = model.getClass().getDeclaredFields();
                int var8 = var7.length;

                for(int var9 = 0; var9 < var8; ++var9) {
                    Field field = var7[var9];
                    if (!field.getName().equalsIgnoreCase("serialVersionUID") && !field.isSynthetic() && field.getAnnotation(ServerIgnore.class) == null) {
                        ServerField serverField = (ServerField)field.getAnnotation(ServerField.class);
                        String k = serverField != null ? serverField.value() : field.getName();
                        if ("".equals(fields)) {
                            fields = k.toUpperCase();
                            values = ":" + k.toUpperCase();
                        } else {
                            fields = fields + "," + k.toUpperCase();
                            values = values + ",:" + k.toUpperCase();
                        }
                    }
                }

                if ("".equals(fields)) {
                    logger.error("bean is empty");
                    throw new SQLException("bean is empty");
                } else {
                    sql = sql.replace("$field$", fields);
                    sql = sql.replace("$value$", values);
                    logger.debug("SQL:" + sql);
                    List<Map<String, Object>> valueMaps = new ArrayList();
                    Iterator var19 = models.iterator();

                    while(var19.hasNext()) {
                        Object o = var19.next();
                        Map<String, Object> obj = new HashMap();
                        Field[] var22 = o.getClass().getDeclaredFields();
                        int var23 = var22.length;

                        for(int var13 = 0; var13 < var23; ++var13) {
                            Field field = var22[var13];
                            field.setAccessible(true);
                            if (!field.getName().equalsIgnoreCase("serialVersionUID") && field.getAnnotation(ServerIgnore.class) == null) {
                                ServerField serverField = (ServerField)field.getAnnotation(ServerField.class);
                                String k = serverField != null ? serverField.value() : field.getName();
                                if (null != field.get(o) && field.get(o).getClass().isEnum()) {
                                    obj.put(k.toUpperCase(), field.get(o).toString());
                                } else {
                                    obj.put(k.toUpperCase(), field.get(o));
                                }
                            }
                        }

                        obj.put("ID", ((BaseModel)o).getId());
                        valueMaps.add(obj);
                    }

                    return this.execBatch(sql, (Map[])valueMaps.toArray(new Map[valueMaps.size()]));
                }
            } else {
                return null;
            }
        } catch (Exception var17) {
            throw new SQLException(var17);
        }
    }

    public int delete(Class resultClass, String id) throws SQLException {
        ServerModel serverModel = (ServerModel)resultClass.getAnnotation(ServerModel.class);
        return this.delete(serverModel != null ? serverModel.value() : resultClass.getName(), " ID=? ", new Object[]{id});
    }

    public int delete(String table, String where) throws SQLException {
        return this.delete(table, where, (Object[])null);
    }

    public int delete(String table, String where, Object[] param) throws SQLException {
        String sql = "DELETE FROM " + table.toUpperCase() + " WHERE ?where?";
        if (BaseUtils.isNotBlank(where)) {
            sql = sql.replace("?where?", where);
        }

        logger.debug("SQL:" + sql);
        return this.exec(sql, param);
    }

    public int delete(String table, String where, Map<String, Object> param) throws SQLException {
        String sql = "DELETE FROM " + table.toUpperCase() + " WHERE ?where?";
        if (BaseUtils.isNotBlank(where)) {
            sql = sql.replace("?where?", where);
        }

        logger.debug("SQL:" + sql);
        return this.exec(sql, param);
    }

    public int delete(String table, String where, Object param) throws SQLException {
        String sql = "DELETE FROM " + table.toUpperCase() + " WHERE ?where?";
        if (BaseUtils.isNotBlank(where)) {
            sql = sql.replace("?where?", where);
        }

        logger.debug("SQL:" + sql);
        return this.exec(sql, param);
    }

    public int[] deleteBatch(String table, List<String> wheres) throws SQLException {
        if (wheres != null) {
            List<String> sqls = new ArrayList();

            String sql;
            for(Iterator var4 = wheres.iterator(); var4.hasNext(); sqls.add(sql)) {
                String where = (String)var4.next();
                sql = "DELETE FROM " + table + " WHERE ?where?";
                if (BaseUtils.isNotBlank(where)) {
                    sql = sql.replace("?where?", where);
                }
            }

            return this.execBatch(sqls);
        } else {
            return null;
        }
    }

    public int[] deleteBatch(String table, String where, Map<String, Object>[] params) throws SQLException {
        String sql = "DELETE FROM " + table.toUpperCase() + " WHERE ?where?";
        if (BaseUtils.isNotBlank(where)) {
            sql = sql.replace("?where?", where);
        }

        logger.debug("SQL:" + sql);
        return this.execBatch(sql, params);
    }

    public int[] deleteBatch(String table, String where, Object[] params) throws SQLException {
        String sql = "DELETE FROM " + table.toUpperCase() + " WHERE ?where?";
        if (BaseUtils.isNotBlank(where)) {
            sql = sql.replace("?where?", where);
        }

        logger.debug("SQL:" + sql);
        return this.execBatch(sql, params);
    }

    public int update(String table, String where, Map<String, Object> record) throws SQLException {
        return this.update(table, where, record, (String)null, (String)null);
    }

    public int update(String table, String where, final Map<String, Object> record, String versionField, String versionValue) throws SQLException {
        if (record == null) {
            logger.error("bean is null");
            throw new SQLException("bean is null");
        } else {
            boolean locked = false;
            if (versionField != null && !"".equalsIgnoreCase(versionField) && versionValue != null && !"".equalsIgnoreCase(versionValue)) {
                record.remove(versionField);
                locked = true;
            }

            final String[] column = new String[record.size()];
            String sql = "UPDATE " + table + " SET $values$ WHERE " + where;
            String values = "";
            if (locked) {
                sql = sql + " and " + versionField + "='" + versionValue + "' ";
            }

            Iterator<String> it = record.keySet().iterator();

            for(int i = 0; it.hasNext(); ++i) {
                String key = (String)it.next();
                column[i] = key;
                if ("".equalsIgnoreCase(values)) {
                    values = key + "=?";
                } else {
                    values = values + "," + key + "=?";
                }
            }

            if ("".equals(values)) {
                logger.error("bean is empty");
                throw new SQLException("bean is empty");
            } else {
                if (locked) {
                    values = values + "," + versionField + "=" + versionField + "+1";
                }

                sql = sql.replace("$values$", values);
                int result = ((Integer)this.getJdbcTemplate().execute(sql, new PreparedStatementCallback<Integer>() {
                    public Integer doInPreparedStatement(PreparedStatement tmt) throws SQLException {
                        int j = 0;

                        for(int len = column.length; j < len; ++j) {
                            Object obj = record.get(column[j]);
                            if (obj != null && obj.getClass().isEnum()) {
                                tmt.setString(j + 1, obj.toString());
                            } else {
                                tmt.setObject(j + 1, obj);
                            }
                        }

                        return tmt.executeUpdate();
                    }
                })).intValue();
                logger.debug("SQL:" + sql);
                if (locked && result == 0) {
                    throw new SQLException("更新失败，数据已经过期。");
                } else {
                    return result;
                }
            }
        }
    }

    public int update(Object model) throws SQLException {
        if (model instanceof BaseModel) {
            BaseModel baseObj = (BaseModel)model;
            if (BaseUtils.isBlank(baseObj.getId())) {
                return 0;
            } else {
                ServerModel serverModel = (ServerModel)model.getClass().getAnnotation(ServerModel.class);
                Map<String, Object> param = new HashMap();
                param.put("ID", ((BaseModel)model).getId());
                return this.update(serverModel != null ? serverModel.value() : model.getClass().getSimpleName(), " ID=:ID ", param, model);
            }
        } else {
            return 0;
        }
    }

    public int update(String table, String where, Map<String, Object> param, Object record) throws SQLException {
        if (record == null) {
            logger.error("bean is null");
            throw new SQLException("bean is null");
        } else {
            try {
                String sql = "";
                Map<String, Object> params = new HashMap();
                sql = " UPDATE " + table.toUpperCase() + " SET $values$ WHERE " + where;
                String values = "";
                ServerModel serverModel = (ServerModel)record.getClass().getAnnotation(ServerModel.class);
                Field[] var9 = record.getClass().getDeclaredFields();
                int var10 = var9.length;

                for(int var11 = 0; var11 < var10; ++var11) {
                    Field field = var9[var11];
                    if (!field.getName().equalsIgnoreCase("serialVersionUID") && !field.isSynthetic() && field.getAnnotation(ServerIgnore.class) == null) {
                        ServerField serverField = (ServerField)field.getAnnotation(ServerField.class);
                        String k = serverField != null ? serverField.value() : field.getName();
                        field.setAccessible(true);
                        Object v = field.get(record);
                        if (v != null) {
                            params.put(k, v);
                            if ("".equals(values)) {
                                values = " " + k.toUpperCase() + "=:" + k;
                            } else {
                                values = values + "," + k.toUpperCase() + "=:" + k;
                            }
                        }
                    }
                }

                sql = sql.replace("$values$", values);
                logger.debug("SQL:" + sql);
                params.putAll(param);
                Iterator var17 = params.entrySet().iterator();

                while(var17.hasNext()) {
                    Map.Entry<String, Object> obj = (Map.Entry)var17.next();
                    if (null != obj && obj.getValue().getClass().isEnum()) {
                        params.put(obj.getKey(), obj.getValue().toString());
                    }
                }

                return this.exec(sql, (Map)params);
            } catch (Exception var16) {
                throw new SQLException(var16);
            }
        }
    }

    public <T> T load(Class<T> resultClass, String id) throws SQLException {
        ServerModel serverModel = (ServerModel)resultClass.getAnnotation(ServerModel.class);
        return this.selectOne(resultClass, "SELECT * FROM " + (serverModel != null ? serverModel.value() : resultClass.getName()) + " WHERE ID=?", (Object[])(new String[]{id}));
    }

    public <T> T selectOne(Class<T> resultClass, String sql) throws SQLException {
        return this.selectOne(resultClass, sql, (Object[])null);
    }

    public <T> T selectOne(Class<T> resultClass, String sql, Object[] param) throws SQLException {
        List<T> list = this.selectList(resultClass, sql, param);
        return list != null && list.size() > 0 ? list.get(0) : null;
    }

    public <T> T selectOne(Class<T> resultClass, String sql, Map<String, Object> param) throws SQLException {
        List<T> list = this.selectList(resultClass, sql, param);
        return list != null && list.size() > 0 ? list.get(0) : null;
    }

    public <T> List<T> selectList(Class<T> resultClass, String sql) throws SQLException {
        return this.selectList(resultClass, sql, (Object[])null);
    }

    public <T> List<T> selectList(Class<T> resultClass, String sql, Object[] param) throws SQLException {
        logger.debug("SQL:" + sql);
        if (!BaseModel.class.isAssignableFrom(resultClass) && !resultClass.getName().startsWith("java.lang.")) {
            return BaseDTO.class.isAssignableFrom(resultClass) ? this.getJdbcTemplate().query(sql, param, new DTOPropertyRowMapper(resultClass)) : (List<T>) this.getJdbcTemplate().queryForList(sql, param);
        } else {
            return this.getJdbcTemplate().query(sql, param, new ModelPropertyRowMapper(resultClass));
        }
    }

    public <T> List<T> selectList(Class<T> resultClass, String sql, Map<String, Object> param) throws SQLException {
        logger.debug("SQL:" + sql);
        if (!BaseModel.class.isAssignableFrom(resultClass) && !resultClass.getName().startsWith("java.lang.")) {
            return BaseDTO.class.isAssignableFrom(resultClass) ? this.getNamedParameterJdbcTemplate().query(sql, param, new DTOPropertyRowMapper(resultClass)) : (List<T>) this.getNamedParameterJdbcTemplate().queryForList(sql, param);
        } else {
            return this.getNamedParameterJdbcTemplate().query(sql, param, new ModelPropertyRowMapper(resultClass));
        }
    }

    public int count(String csql) throws SQLException {
        return this.count(csql, (Object[])null);
    }

    public int count(String csql, Object[] param) throws SQLException {
        String sql = "SELECT COUNT(*) AS t " + SqlUtils.removeOrders(SqlUtils.removeSelect(csql));
        logger.debug("SQL:" + sql);
        return ((Integer)this.getJdbcTemplate().queryForObject(sql, param, Integer.class)).intValue();
    }

    public int count(String csql, Map<String, Object> param) throws SQLException {
        String sql = "SELECT COUNT(*) AS t " + SqlUtils.removeOrders(SqlUtils.removeSelect(csql));
        logger.debug("SQL:" + sql);
        return ((Integer)this.getNamedParameterJdbcTemplate().queryForObject(sql, param, Integer.class)).intValue();
    }

    public <T> PageVO<T> pageQuery(Class<T> resultClass, String sql, int pageNo, int pageSize) throws SQLException {
        return this.pageQuery(resultClass, sql, (Object[])null, pageNo, pageSize);
    }

    public <T> PageVO<T> pageQuery(Class<T> resultClass, String sql, Object[] param, int pageNo, int pageSize) throws SQLException {
        List<T> result = new ArrayList(0);
        int total = this.count(sql, param);
        if (total < 1) {
            return new PageVO();
        } else {
            if (pageNo < 1) {
                pageNo = 1;
            }

            if (pageSize < 1) {
                pageSize = total;
            }

            int startIndex = PageVO.getStartOfPage(pageNo, pageSize);
            if (total > 0) {
                IDialect dialectImp = new SQLServer2005Dialect();
                if ("DB2".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new DB2Dialect();
                } else if ("DERBY".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new DerbyDialect();
                } else if ("MYSQL".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new MySQLDialect();
                } else if ("ORACLE".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new OracleDialect();
                } else if ("SQLSERVER".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new SQLServer2005Dialect();
                }

                String csql = ((IDialect)dialectImp).getPaginationString(sql, startIndex, pageSize);
                result = this.selectList(resultClass, csql, param);
            }

            return new PageVO(startIndex, total, pageSize, (List)result);
        }
    }

    public <T> PageVO<T> pageQuery(Class<T> resultClass, String sql, Map<String, Object> param, int pageNo, int pageSize) throws SQLException {
        List<T> result = new ArrayList(0);
        int total = this.count(sql, param);
        if (total < 1) {
            return new PageVO();
        } else {
            if (pageNo < 1) {
                pageNo = 1;
            }

            if (pageSize < 1) {
                pageSize = total;
            }

            int startIndex = PageVO.getStartOfPage(pageNo, pageSize);
            if (total > 0) {
                IDialect dialectImp = new SQLServer2005Dialect();
                if ("DB2".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new DB2Dialect();
                } else if ("DERBY".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new DerbyDialect();
                } else if ("MYSQL".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new MySQLDialect();
                } else if ("ORACLE".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new OracleDialect();
                } else if ("SQLSERVER".equalsIgnoreCase(this.dialect)) {
                    dialectImp = new SQLServer2005Dialect();
                }

                String csql = ((IDialect)dialectImp).getPaginationString(sql, startIndex, pageSize);
                result = this.selectList(resultClass, csql, param);
            }

            return new PageVO(startIndex, total, pageSize, (List)result);
        }
    }

    public synchronized String getSeq(String bz, String table, String pk) {
        int seq = 1;
        String date = BaseUtils.formatDate(new Date(), "yyyyMMddHHmmss");

        String sseq;
        String rnd;
        try {
            sseq = "SELECT TOP 1 " + pk + " as pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC";
            if ("DB2".equalsIgnoreCase(this.dialect)) {
                sseq = "SELECT  " + pk + " AS pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC FETCH FIRST 1 ROWS ONLY";
            } else if ("DERBY".equalsIgnoreCase(this.dialect)) {
                sseq = "SELECT " + pk + " AS pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC LIMIT 1";
            } else if ("MYSQL".equalsIgnoreCase(this.dialect)) {
                sseq = "SELECT " + pk + " AS pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC LIMIT 1";
            } else if ("ORACLE".equalsIgnoreCase(this.dialect)) {
                sseq = "SELECT * FROM ( SELECT " + pk + " AS pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC) WHERE ROWNUM=1";
            } else if ("SQLSERVER".equalsIgnoreCase(this.dialect)) {
                sseq = "SELECT TOP 1 " + pk + " AS pk FROM " + table + " WHERE " + pk + " LIKE '" + bz + date + "%' ORDER BY " + pk + " DESC";
            }

            rnd = (String)this.selectOne(String.class, sseq);
            if (rnd == null) {
                seq = 0;
            } else {
                rnd = rnd.substring((bz + date).length(), rnd.length() - 3);
                if ("".equalsIgnoreCase(rnd)) {
                    seq = 0;
                } else {
                    seq = Integer.parseInt(rnd);
                }
            }

            if (seq == 0) {
                seq = 1;
            } else {
                ++seq;
            }
        } catch (SQLException var10) {
            ;
        }

        sseq = "";
        if (seq < 10) {
            sseq = "00" + seq;
        } else if (seq < 100) {
            sseq = "0" + seq;
        } else {
            sseq = seq + "";
        }

        rnd = "";
        Random r = new Random((long)((int)(Math.random() * 100.0D)));
        int rint = r.nextInt(100);
        if (rint < 10) {
            rnd = "00" + rint;
        } else if (rint < 100) {
            rnd = "0" + rint;
        } else {
            rnd = rint + "";
        }

        return bz + date + sseq + rnd;
    }

    public String getUUID() {
        return UUIDUtils.getUUID();
    }

    public Map<String, Object> converModelToMap(Object model) {
        if (model != null && model instanceof BaseModel) {
            ServerModel serverModel = (ServerModel)model.getClass().getAnnotation(ServerModel.class);
            Map<String, Object> bean = (Map)Arrays.asList(model.getClass().getDeclaredFields()).parallelStream().filter((o) -> {
                return !o.getName().equalsIgnoreCase("serialVersionUID") && !o.isSynthetic() && o.getAnnotation(ServerIgnore.class) == null;
            }).collect(toMap((o) -> {
                ServerField serverField = (ServerField)o.getAnnotation(ServerField.class);
                return serverField != null ? serverField.value() : o.getName();
            }, (o) -> {
                o.setAccessible(true);

                try {
                    return o.get(model);
                } catch (Exception var3) {
                    logger.error("insert error:" + var3.getMessage());
                    return null;
                }
            }));
            bean.put("ID", ((BaseModel)model).getId());
            return bean;
        } else {
            return null;
        }
    }

    public <T> T converMapToModel(Class<T> resultClass, Map<String, Object> map) {
        if (map == null) {
            return null;
        } else {
            ServerModel serverModel = (ServerModel)resultClass.getAnnotation(ServerModel.class);
            if (serverModel != null) {
                try {
                    Object obj = resultClass.newInstance();
                    Field[] var5 = resultClass.getDeclaredFields();
                    int var6 = var5.length;

                    for(int var7 = 0; var7 < var6; ++var7) {
                        Field field = var5[var7];
                        if (!field.getName().equalsIgnoreCase("serialVersionUID") && !field.isSynthetic() && field.getAnnotation(ServerIgnore.class) == null) {
                            ServerField serverField = (ServerField)field.getAnnotation(ServerField.class);
                            String k = serverField != null ? serverField.value() : field.getName();
                            field.setAccessible(true);
                            field.set(obj, map.get(k));
                        }
                    }

                    Object objId = map.get("ID");
                    ((BaseModel)obj).setId(objId != null ? (String)objId : null);
                    return (T) obj;
                } catch (Exception var11) {
                    ;
                }
            }

            return null;
        }
    }

    public <T> T converModelToDTO(Class<T> resultClass, Object model) {
        if (model == null) {
            return null;
        } else {
            if (model instanceof BaseModel) {
                try {
                    Object obj = resultClass.newInstance();
                    Field[] var4 = resultClass.getDeclaredFields();
                    int var5 = var4.length;

                    for(int var6 = 0; var6 < var5; ++var6) {
                        Field field = var4[var6];
                        if (!field.getName().equalsIgnoreCase("serialVersionUID") && !field.isSynthetic() && field.getAnnotation(ServerIgnore.class) == null) {
                            String k = field.getName();
                            field.setAccessible(true);

                            try {
                                Field sField = model.getClass().getDeclaredField(this.converDTONameToModelName(k));
                                sField.setAccessible(true);
                                field.set(obj, sField.get(model));
                            } catch (NoSuchFieldException var11) {
                                ;
                            }
                        }
                    }

                    try {
                        Field sField = resultClass.getDeclaredField("id");
                        sField.setAccessible(true);
                        sField.set(obj, ((BaseModel)model).getId());
                    } catch (NoSuchFieldException var10) {
                        ;
                    }

                    return (T) obj;
                } catch (Exception var12) {
                    ;
                }
            }

            return null;
        }
    }

    public <T> T converDTOToModel(Class<T> resultClass, Object dto) {
        if (dto == null) {
            return null;
        } else {
            ServerModel serverModel = (ServerModel)resultClass.getAnnotation(ServerModel.class);
            if (serverModel != null) {
                try {
                    Object obj = resultClass.newInstance();
                    Field[] var5 = resultClass.getDeclaredFields();
                    int var6 = var5.length;

                    for(int var7 = 0; var7 < var6; ++var7) {
                        Field field = var5[var7];
                        if (!field.getName().equalsIgnoreCase("serialVersionUID") && !field.isSynthetic() && field.getAnnotation(ServerIgnore.class) == null) {
                            String k = field.getName();
                            field.setAccessible(true);

                            try {
                                Field sField = dto.getClass().getDeclaredField(this.converModelNameToDTOName(k));
                                sField.setAccessible(true);
                                field.set(obj, sField.get(dto));
                            } catch (NoSuchFieldException var12) {
                                ;
                            }
                        }
                    }

                    try {
                        Field sField = dto.getClass().getDeclaredField("id");
                        sField.setAccessible(true);
                        Object objId = sField.get(dto);
                        ((BaseModel)obj).setId(objId != null ? (String)objId : null);
                    } catch (NoSuchFieldException var11) {
                        ;
                    }

                    return (T) obj;
                } catch (Exception var13) {
                    ;
                }
            }

            return null;
        }
    }

    private String converModelNameToDTOName(String modelName) {
        String dtoName = "";
        int findex = 0;

        for(int i = 0; i < modelName.length(); ++i) {
            char c = modelName.charAt(i);
            if (Character.isUpperCase(c)) {
                ++findex;
                if (findex == 1) {
                    dtoName = dtoName + "_" + Character.toString(c).toLowerCase();
                } else {
                    dtoName = dtoName + Character.toString(c).toLowerCase();
                }
            } else {
                findex = 0;
                dtoName = dtoName + Character.toString(c);
            }
        }

        return dtoName;
    }

    private String converDTONameToModelName(String dtoName) {
        String modelName = "";
        String[] dtoNames = dtoName.split("_");
        int i = 0;
        String[] var5 = dtoNames;
        int var6 = dtoNames.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            String s = var5[var7];
            if (i == 0) {
                modelName = s;
            } else {
                modelName = modelName + s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
            }

            ++i;
        }

        return modelName;
    }

    public boolean exists(String sql, final Object[] param) {
        sql = "SELECT EXISTS ( " + sql + " )";
        return ((Boolean)this.getJdbcTemplate().execute(sql, new PreparedStatementCallback<Boolean>() {
            public Boolean doInPreparedStatement(PreparedStatement tmt) throws SQLException {
                if (param != null && param.length > 0) {
                    int i = 0;

                    for(int len = param.length; i < len; ++i) {
                        if (param[i] != null && param[i].getClass().isEnum()) {
                            tmt.setString(i + 1, param[i].toString());
                        } else {
                            tmt.setObject(i + 1, param[i]);
                        }
                    }
                }

                ResultSet rs = tmt.executeQuery();
                return rs.next() ? rs.getInt(1) == 1 : false;
            }
        })).booleanValue();
    }

    public boolean exists(String sql, Map<String, Object> param) {
        sql = "SELECT EXISTS ( " + sql + " )";
        return ((Boolean)this.getNamedParameterJdbcTemplate().execute(sql, param, new PreparedStatementCallback<Boolean>() {
            public Boolean doInPreparedStatement(PreparedStatement tmt) throws SQLException, DataAccessException {
                ResultSet rs = tmt.executeQuery();
                return rs.next() ? rs.getInt(1) == 1 : false;
            }
        })).booleanValue();
    }

    private boolean matches(Pattern pattern, String dataString) {
        Matcher matcher = pattern.matcher(dataString);
        return matcher.matches();
    }

    private static List<Pattern> getValidationPatterns() {
        List<Pattern> patterns = new ArrayList();
        String[] var1 = sqlRegexps;
        int var2 = var1.length;

        for(int var3 = 0; var3 < var2; ++var3) {
            String sqlExpression = var1[var3];
            patterns.add(getPattern(sqlExpression));
        }

        return patterns;
    }

    private static Pattern getPattern(String regEx) {
        return Pattern.compile(regEx, 66);
    }

    private boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    public boolean isSQLSafe(String dataString) {
        if (this.isEmpty(dataString)) {
            return true;
        } else {
            Iterator var2 = this.validationPatterns.iterator();

            Pattern pattern;
            do {
                if (!var2.hasNext()) {
                    return true;
                }

                pattern = (Pattern)var2.next();
            } while(!this.matches(pattern, dataString));

            return false;
        }
    }

    public String checkSQLSafe(String dataString) throws SQLException {
        if (!this.isSQLSafe(dataString)) {
            throw new SQLException("unsafed parameter");
        } else {
            return dataString;
        }
    }
}
